package cc.rengu.igas.momp.core.service.trans;

import cc.rengu.igas.momp.common.constant.CommonConstant;
import cc.rengu.igas.momp.common.dao.McAccountInfoMapper;
import cc.rengu.igas.momp.common.dao.impl.McAccountInfoMapperImpl;
import cc.rengu.igas.momp.common.entity.TMAccountInfo;
import cc.rengu.igas.momp.common.enums.RespCodeEnum;
import cc.rengu.igas.momp.facade.request.ManageCashierAccountRequest;
import cc.rengu.igas.momp.facade.response.ManageCashierAccountResponse;
import cc.rengu.igas.smps.facade.base.Header;
import cc.rengu.igas.smps.facade.request.BankAcctInfoQueryRequest;
import cc.rengu.igas.smps.facade.response.BankAcctInfoQueryResponse;
import cc.rengu.igas.smps.facade.result.Result;
import cc.rengu.oltp.service.base.RadpService;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.entity.BinInfo;
import cc.rengu.oltp.service.common.entity.SysParam;
import cc.rengu.oltp.service.common.enums.ChannelEnum;
import cc.rengu.oltp.service.common.enums.OltpRpcdEnum;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.service.realize.BinInfoService;
import cc.rengu.oltp.service.realize.SysParamService;
import cc.rengu.oltp.service.realize.impl.BinInfoServiceImpl;
import cc.rengu.oltp.service.realize.impl.DubboServiceImpl;
import cc.rengu.oltp.service.realize.impl.SysParamServiceImpl;
import cc.rengu.oltp.utility.util.ConvertUtil;
import cc.rengu.oltp.utility.util.DateUtil;
import cc.rengu.oltp.utility.util.XmlTreeUtil;
import cc.rengu.utility.base.StringUtil;
import cc.rengu.utility.dbs.Database;
import com.alibaba.fastjson.JSON;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 收银员收款账号配置
 *
 * @author Jinan Liu
 * @date 2020/4/2 17:49
 * @description
 */
public class CashierAccountManageService extends RadpService {
    private String globalInstId;
    private String userId;
    private String acctNo;

    @Override
    protected int bizInit(String s) {
        return CommonConstant.PROCESS_SUCCESS;
    }

    @Override
    protected int bizProcess(String s, int i) {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();

        try {

            ManageCashierAccountRequest manageCashierAccountRequest = new ManageCashierAccountRequest();
            ConvertUtil.convertOutput(manageCashierAccountRequest);

            ManageCashierAccountResponse manageCashierAccountResponse = new ManageCashierAccountResponse();
            manageCashierAccountResponse.setHeader(manageCashierAccountRequest.getHeader());
            BizResponse<ManageCashierAccountResponse> bizResponse = new BizResponse<>();
            bizResponse.setResult(manageCashierAccountResponse);

            globalInstId = manageCashierAccountRequest.getHeader().getInstId();
            userId = manageCashierAccountRequest.getUserId();
            acctNo = manageCashierAccountRequest.getAcctInfo().getAcctNo();
            /* 检查操作员机构标示 */
            if (StringUtil.isNullorEmpty(globalInstId)) {
                rglog.error("法人机构号<{}>为空!", globalInstId);
                throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
            }

            // 服务调用
            BizResponse<ManageCashierAccountResponse> bizResponseNew = cashierAccountManage(xmlTreeUtil, manageCashierAccountRequest, manageCashierAccountResponse);

            ConvertUtil.convertInput(bizResponseNew.getResult());

        } catch (BizException e) {
            try {
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_CODE, e.getCode());
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_DESC, e.getMessage());
                xmlTreeUtil.setXmlTreeStringValue(CommonConstant.KEY_RESPDESC, e.getMessage());
            } catch (Exception e1) {
                rglog.error(StringUtil.ExceptionToString(e1));
            }
        } catch (Exception e) {
            rglog.error(StringUtil.ExceptionToString(e));
            try {
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_CODE, OltpRpcdEnum.OLTP_PROCESS_ERROR.getRespCode());
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_DESC, OltpRpcdEnum.OLTP_PROCESS_ERROR.getRespDesc());
                xmlTreeUtil.setXmlTreeStringValue(CommonConstant.KEY_RESPDESC, e.getMessage());
            } catch (Exception e1) {
                rglog.error(StringUtil.ExceptionToString(e));
            }
        }

        return CommonConstant.PROCESS_SUCCESS;
    }

    @Override
    protected int bizTerminate(String s) {
        return CommonConstant.PROCESS_SUCCESS;
    }

    /**
     * 收银员收款账号配置
     *
     * @param xmlTreeUtil                  内部XML树
     * @param manageCashierAccountRequest  收银员收款账号配置接口请求报文
     * @param manageCashierAccountResponse 收银员收款账号配置接口应答报文
     * @return cc.rengu.oltp.service.model.BizResponse<cc.rengu.igas.momp.facade.response.ManageCashierAccountResponse>收银员收款账号配置接口应答报文
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @date 2020/5/28 14:50
     */

    private BizResponse<ManageCashierAccountResponse> cashierAccountManage(XmlTreeUtil xmlTreeUtil, ManageCashierAccountRequest manageCashierAccountRequest, ManageCashierAccountResponse manageCashierAccountResponse) throws Exception {

        BizResponse<ManageCashierAccountResponse> bizResponse = new BizResponse<>();
        //查询上送用户的卡bin信息
        BinInfoService binInfoService = new BinInfoServiceImpl();
        BinInfo binInfo = binInfoService.getCardBinInfo(acctNo);
        if (null == binInfo) {
            rglog.info("通过银行卡号<{}> 查询卡bin信息为空！无法判断上送账号是否为本行借记卡", acctNo);
            throw new BizException(RespCodeEnum.NOT_PROFESSIONAL_DEBIT_CARD.getRespCode(), RespCodeEnum.NOT_PROFESSIONAL_DEBIT_CARD.getRespDesc());
        }
        SysParamService sysParamService = new SysParamServiceImpl();
        SysParam sysParam = sysParamService.getSysParamInfo(globalInstId, CommonConstant.OPMS_SYS_PARAM, CommonConstant.CORPORATION_ORG_CODE);
        if (null == sysParam || null == sysParam.getParamStatus()) {
            rglog.info("法人行机构编码未配置或配置失效,instId:<{}>", globalInstId);
            throw new BizException(RespCodeEnum.NOT_PROFESSIONAL_DEBIT_CARD.getRespCode(), RespCodeEnum.NOT_PROFESSIONAL_DEBIT_CARD.getRespDesc());
        }
        if (sysParam.getParamValue().contains(binInfo.getIssuerCode().substring(0, 4))) {
            /* 本行卡 */
            if (binInfo.getCardType().equals("1")) {
                rglog.info("上送账号为本行借记卡,判断通过！");
            } else {
                rglog.info("上送账号为本行卡但非本行借记卡,判断不通过！");
                throw new BizException(RespCodeEnum.NOT_PROFESSIONAL_DEBIT_CARD.getRespCode(), RespCodeEnum.NOT_PROFESSIONAL_DEBIT_CARD.getRespDesc());
            }
        } else {
            /* 他行卡 */
            rglog.info("上送账号为他行卡,判断不通过！");
            throw new BizException(RespCodeEnum.NOT_PROFESSIONAL_DEBIT_CARD.getRespCode(), RespCodeEnum.NOT_PROFESSIONAL_DEBIT_CARD.getRespDesc());

        }
        //调用esb接口查询卡状态 卡所属人是否正常
        checkCardStatus(manageCashierAccountRequest);
        /* 先查询收银员信息表 */
        rglog.info("流水号<{}>:法人机构号<{}>用户标识<{}>账号<{}>查询收银员信息表开始...", manageCashierAccountRequest.getHeader().getTraceNo(), globalInstId, userId, acctNo);
        McAccountInfoMapper mcAccountInfoMapper = new McAccountInfoMapperImpl();
        TMAccountInfo tmAccountInfo = mcAccountInfoMapper.selectAccountByUserIdAcctNo(globalInstId, userId, acctNo);
        if (null != tmAccountInfo) {
            //修改 tmAccountInfo
            tmAccountInfo = updateAccountInfo(tmAccountInfo, manageCashierAccountRequest);
            int returnCode = mcAccountInfoMapper.updateMcAccountInfo(tmAccountInfo);
            if (Database.DBS_SUCCESS != returnCode) {
                rglog.error("更新收银员信息失败! RETURN_CODE=<{}>", returnCode);
                throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
            }
            rglog.info("更新收银员信息成功，用户标识<{}>账号<{}>", userId, acctNo);
        } else {
            rglog.info("法人机构号<{}>用户标识<{}>账号<{}>新增收银员信息表开始...", manageCashierAccountRequest.getHeader().getTraceNo(), globalInstId, userId, acctNo);
            tmAccountInfo = convertAccountInfo(tmAccountInfo, manageCashierAccountRequest);
            int ReturnCode = mcAccountInfoMapper.insertMcAccountInfo(tmAccountInfo);
            if (Database.DBS_SUCCESS != ReturnCode) {
                /* 异常结束数据库事务 */
                rglog.error("新增收银员信息失败, 用户标识<{}>, 账号<{}>", userId, acctNo);
                throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
            }
        }
        bizResponse.setRspSysId(ChannelEnum.MOMP.getChannelType());
        bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
        manageCashierAccountResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        manageCashierAccountResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
        bizResponse.setResult(manageCashierAccountResponse);

        return bizResponse;
    }

    /**
     * @param tmAccountInfo               收银员信息实体类
     * @param manageCashierAccountRequest 收银员收款账号配置接口请求报文
     * @return
     * @throws BizException
     */
    private TMAccountInfo convertAccountInfo(TMAccountInfo tmAccountInfo, ManageCashierAccountRequest manageCashierAccountRequest) throws BizException {
        TMAccountInfo tmAccountInfo1 = new TMAccountInfo();
        /** 机构号*/
        tmAccountInfo1.setInstId(globalInstId);
        /** 用户标识*/
        tmAccountInfo1.setUserId(manageCashierAccountRequest.getUserId());
        /** 用户账号*/
        tmAccountInfo1.setUserAcct(manageCashierAccountRequest.getAcctInfo().getAcctNo());
        /**账号名称*/
        tmAccountInfo1.setUserName(manageCashierAccountRequest.getAcctInfo().getAcctName());
        /**证件类型*/
        tmAccountInfo1.setCertType(manageCashierAccountRequest.getAcctInfo().getIdType());
        /**证件号码*/
        tmAccountInfo1.setCertNo(manageCashierAccountRequest.getAcctInfo().getIdNo());
        /**预留手机号*/
        tmAccountInfo1.setMobileNo(manageCashierAccountRequest.getAcctInfo().getCellPhoneNumber());
        /**创建人*/
        tmAccountInfo1.setOprId(userId);
        /**创建时间*/
        tmAccountInfo1.setCreateTime(new SimpleDateFormat(CommonConstant.TIMESTAMP_FORMAT).format(new Date()));

        return tmAccountInfo1;
    }

    /**
     * 修改收银员信息表 实体
     *
     * @param tmAccountInfo               收银员信息实体类
     * @param manageCashierAccountRequest 收银员收款账号配置接口请求报文
     * @return
     * @throws BizException
     */
    private TMAccountInfo updateAccountInfo(TMAccountInfo tmAccountInfo, ManageCashierAccountRequest manageCashierAccountRequest) throws BizException {
        /** 用户账号*/
        tmAccountInfo.setUserAcct(manageCashierAccountRequest.getAcctInfo().getAcctNo());
        /**账号名称*/
        tmAccountInfo.setUserName(manageCashierAccountRequest.getAcctInfo().getAcctName());
        /**证件类型*/
        tmAccountInfo.setCertType(manageCashierAccountRequest.getAcctInfo().getIdType());
        /**证件号码*/
        tmAccountInfo.setCertNo(manageCashierAccountRequest.getAcctInfo().getIdNo());
        /**预留手机号*/
        tmAccountInfo.setMobileNo(manageCashierAccountRequest.getAcctInfo().getCellPhoneNumber());
        /**最后修改人*/
        tmAccountInfo.setLastOprId(userId);
        /**修改时间*/
        tmAccountInfo.setUpdateTime(new SimpleDateFormat(CommonConstant.TIMESTAMP_FORMAT).format(new Date()));
        return tmAccountInfo;
    }

    /**
     * @param manageCashierAccountRequest 请求实体类
     * @return
     * @throws BizException
     * @author pangjl
     * @date 20201/3/29
     */
    private void checkCardStatus(ManageCashierAccountRequest manageCashierAccountRequest) throws Exception {
        Header header = new Header();
        header.setVersion("1.0.0");
        header.setInstId(globalInstId);
        header.setSrcSysId(AppParamConstant.SYS_ID);
        header.setChanlId("MOMP");
        header.setBizType("00");
        header.setTransDate(DateUtil.getCurrentDate());
        header.setTransTime(DateUtil.getCurrentTime());
        header.setTxnNum("00010000200000");
        header.setTraceNo(manageCashierAccountRequest.getHeader().getTraceNo());

        //设置客户账户信息查询请求体，分支机构号 字段未送
        BankAcctInfoQueryRequest coreAcctInfoQueryRequest = new BankAcctInfoQueryRequest();
        coreAcctInfoQueryRequest.setAcctNo(manageCashierAccountRequest.getAcctInfo().getAcctNo());
        coreAcctInfoQueryRequest.setHeader(header);
        rglog.debug("客户账户信息查询请求:<{}>", JSON.toJSONString(coreAcctInfoQueryRequest));
        DubboServiceImpl dubboService = new DubboServiceImpl();
        Result<BankAcctInfoQueryResponse> result = (Result<BankAcctInfoQueryResponse>) dubboService.callDubboService("bankSupService", "bankAcctInfoQuery", coreAcctInfoQueryRequest);
        if (null == result || null == result.getResult()) {
            rglog.info("调用通道接口失败");
            throw new BizException(RespCodeEnum.CARD_QUERY_ERROR.getRespCode(), RespCodeEnum.CARD_QUERY_ERROR.getRespDesc());
        } else if (!result.isSuccess() || !"00000000".equals(result.getResult().getRespCode())) {
            rglog.info("调用通道接口成功，查询卡号信息失败");
            throw new BizException(RespCodeEnum.CARD_QUERY_ERROR.getRespCode(), RespCodeEnum.CARD_QUERY_ERROR.getRespDesc());
        } else {
            //交易成功
            rglog.error("调用通道查询账户信息成功");
            String cardStatus = result.getResult().getAcctStatus();
            //卡状态  0正常
            if (!cardStatus.equals(CommonConstant.ZERO_COMMON_CONSTANT)) {
                rglog.info("卡状态不正常<{}>", cardStatus);
                throw new BizException(RespCodeEnum.CRAD_STATUS_ERROR.getRespCode(), RespCodeEnum.CRAD_STATUS_ERROR.getRespDesc());
            }
            //TODO POC演示 挡板不校验户名;后续解开
            /*if (!manageCashierAccountRequest.getAcctInfo().getAcctName().equals(result.getResult().getCustomerName())) {
                rglog.info("上送账户名称<{}>与卡所属账户名称<{}>不符", manageCashierAccountRequest.getAcctInfo().getAcctName(), result.getResult().getCustomerName());
                throw new BizException(RespCodeEnum.CARD_NAME_ERROR.getRespCode(), RespCodeEnum.CARD_NAME_ERROR.getRespDesc());
            }*/
        }
    }
}
